using System;
using NUnit.Framework;
using ValidationFramework.Reflection;

namespace ValidationFramework.Tests
{
    public class RequiredEnumRuleTest
    {
        private enum Values
        {
            Two,
            One
        }


        const string expectedErrorMessage = "expectedErrorMessage";
        const string expectedRuleSet = "EXPECTEDRULESET";

        [TestFixture]
        public class Construction
        {
            [Test]
            public void Simple1()
            {
                var rule = new RequiredRule<Values>
                           	{
								InitialValue = Values.One
                           	};
                Assert.AreEqual(Values.One, rule.InitialValue);
            }


            [Test]
            public void Simple2()
            {
                var rule = new RequiredRule<Values>();
            }


            [Test]
            public void Simple3()
            {
                var rule = new RequiredRule<Values>();
            }


            [Test]
            public void Simple4()
            {
                var rule = new RequiredRule<Values>();
                Assert.IsNull(rule.ErrorMessage);
            }

        }
        [TestFixture]
        public class IsEquivalent
        {
            [Test]
            public void Simple()
            {
                var rule1 = new RequiredRule<Values>
                            	{
                            		InitialValue = Values.One
                            	};
				var rule2 = new RequiredRule<Values>
				{
					InitialValue = Values.One
				};
                Assert.IsTrue(rule1.IsEquivalent(rule2));

				rule1 = new RequiredRule<Values>
				{
					InitialValue = Values.One
				};
				rule2 = new RequiredRule<Values>
				{
					InitialValue = Values.One
				};
                Assert.IsFalse(rule1.IsEquivalent(rule2));

            }

        }
        [TestFixture]
        public class Validate
        {
            [Test]
            public void NotNullable()
            {
                var rule = new RequiredRule<Values>();
                rule.CheckType(new MockInfoDescriptor(typeof(Values).TypeHandle, "foo"));
                Assert.IsTrue(rule.Validate(null, Values.One, null, null));
                Assert.IsTrue(rule.Validate(null, Values.Two, null, null));

				var rule2 = new RequiredRule<Values>
				{
					InitialValue = Values.One
				};
                rule.CheckType(new MockInfoDescriptor(typeof(Values).TypeHandle, "foo"));
                Assert.IsTrue(rule2.Validate(null, Values.Two, null, null));
                Assert.IsFalse(rule2.Validate(null, Values.One, null, null));

            }
            [Test]
            public void Nullable()
            {
                var rule = new RequiredRule<Values>();
                rule.CheckType(new MockInfoDescriptor(typeof(Values?).TypeHandle, "foo"));
                Assert.IsFalse(rule.Validate(null, null, null, null));
                Assert.IsTrue(rule.Validate(null, Values.One, null, null));
                Assert.IsTrue(rule.Validate(null, Values.Two, null, null));

				var rule2 = new RequiredRule<Values>
				{
					InitialValue = Values.One
				};
                rule.CheckType(new MockInfoDescriptor(typeof(Values?).TypeHandle, "foo"));
                Assert.IsTrue(rule2.Validate(null, null, null, null));
                Assert.IsFalse(rule2.Validate(null, Values.Two, null, null));
                Assert.IsTrue(rule2.Validate(null, Values.One, null, null));
            }

        }
        [TestFixture]
        public class RuleInterpretation
        {
            [Test]
            public void Simple()
            {
                var rule = new RequiredRule<Values>();
                rule.CheckType(new MockInfoDescriptor(typeof(Values?).TypeHandle, "foo"));
                Assert.IsNotNull(rule.RuleInterpretation);
            }
        }


        [TestFixture]
        public class CheckTypes
        {
            [Test]
            public void Simple()
            {
				var rule = new RequiredRule<Values>
				{
					InitialValue = Values.One
				};
                rule.CheckType(new MockInfoDescriptor(typeof (Values).TypeHandle, "foo"));
            }


            [Test]
            [ExpectedException(typeof(ArgumentException), ExpectedMessage = "Member 'foo' must be a 'ValidationFramework.Tests.RequiredEnumRuleTest+Values' to be used for the ValidationFramework.RequiredRule<ValidationFramework.Tests.RequiredEnumRuleTest+Values>. Actual Type 'System.Int32'.\r\nParameter name: value")]
            public void CheckTypesException1()
            {
				var rule = new RequiredRule<Values>()
				{
					InitialValue = Values.Two
				};
                rule.CheckType(new MockInfoDescriptor(TypePointers.IntTypeHandle, "foo"));
            }
        }

    }
}